package config;

import first.MyTestBean;
import org.springframework.context.annotation.Bean;
import pojo.Person;
import pojo.TestBean;
import pojo.destroy.*;
import service.UserService;
import service.impl.UserServiceImpl;
import service.impl.UserServiceImplTest;

/**
 * @author: ZhouBert
 * @date: 2020/7/26
 * @description:
 */
public class AppConfig {

	public static final String XML_PATH = "/applicationContext.xml";

	@Bean
	public Person person() {
		return new Person();
	}

	@Bean
	public MyTestBean myTestBean() {
		return new MyTestBean();
	}

	@Bean
	public UserService userService(){
		System.out.println("调用了 AppConfig 里的 userService");
		return new UserServiceImpl();
	}

	/**
	 * 实验 isOverriddenByExistingDefinition ：
	 * 由于本方法 与上一个方法 bean name 重复 + 处于同一个配置类中，于是本方法根本不会被调用！
	 * @return
	 */
	@Bean("userService")
	public UserService userService2(){
		System.out.println("22222 调用了 AppConfig 里的 userService2 ");
		return new UserServiceImplTest();
	}

	/**
	 * 从官方注释可以看出，
	 * 注解上，@Bean 的方法 -- XML上，factory-bean 的 factory-method（用于实例化复杂对象）；
	 * 实际上，对于 spring 的源码，就是把 @Bean 当成 factory method 处理的
	 * @return
	 */
	@Bean
	public static Person testPerson(){
		return new Person("static-factory-method",0);
	}

	/**
	 * 传入 一个 bean 是可以的，但是传入一个 String 是会报异常的！-> NoSuchBeanDefinitionException
	 * @param person
	 * @return
	 */
	@Bean
	public TestBean testBean(Person person){
		return new TestBean();
	}

	/**
	 * 当没有下面的 testBean(person,myTestBean) 时，这个和上面的 testBean 会导致报错！
	 * 因为本 testBean 和上面的 testBean 都拥有同样的 public + 方法参数！
	 * @param myTestBean
	 * @return
	 */
	@Bean
	public TestBean testBean(MyTestBean myTestBean){
		return new TestBean();
	}

	/**
	 * 当这三个 testBean 同时存在时，spring 就会调用参数最多的 testBean
	 * @param person
	 * @param myTestBean
	 * @return
	 */
	@Bean
	public TestBean testBean(Person person, MyTestBean myTestBean){
		// 也就是 这个方法会被调用到！
		System.out.println("longest testBean ");
		return new TestBean();
	}

	//region	测试 bean 的注销

	@Bean
	public DestroyBeanByDisposableBean destroyBeanByDisposableBean(){
		return new DestroyBeanByDisposableBean();
	}

	@Bean
	public DestroyBeanByPreDestroy destroyBeanByPreDestroy(){
		return new DestroyBeanByPreDestroy();
	}

	@Bean
	public DestroyBeanByAutoCloseable destroyBeanByAutoCloseable(){
		return new DestroyBeanByAutoCloseable();
	}

	@Bean
	public DestroyBeanByNameClose destroyBeanByNameClose(){
		return new DestroyBeanByNameClose();
	}

	@Bean
	public DestroyBeanByNameShutdown destroyBeanByNameShutdown(){
		return new DestroyBeanByNameShutdown();
	}

	@Bean
	public DestroyBeanByDestructionAwareBeanPostProcessor destroyBeanByDestructionAwareBeanPostProcessor(){
		return new DestroyBeanByDestructionAwareBeanPostProcessor();
	}

	//endregion



}
